package com.usian.comment.service.impl;

import com.usian.comment.entity.ApComment;
import com.usian.comment.entity.ApCommentLike;
import com.usian.comment.service.CommentService;
import com.usian.comment.vo.CommentVo;
import com.usian.common.aliyun.GreenTextScan;
import com.usian.common.constants.message.HotArticleConstants;
import com.usian.common.enums.AppHttpCodeEnum;
import com.usian.common.exception.LeadException;
import com.usian.common.threadlocal.UserThreadLocalUtils;
import com.usian.common.util.BeanHelper;
import com.usian.common.util.JsonUtils;
import com.usian.model.article.msg.ArticleBehaviorMsg;
import com.usian.model.comment.dtos.CommentDto;
import com.usian.model.comment.dtos.CommentLikeDto;
import com.usian.model.comment.dtos.CommentSaveDto;
import com.usian.model.user.dtos.UserInfoDto;
import com.usian.user.client.UserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotBlank;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private GreenTextScan textScan;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    public void saveComment(CommentSaveDto dto) {
        //1、参数校验
        if(dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2、从线程中获取用户id，判断用户登录状态
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }

        //调用阿里云，对评论内容进行文本审核
        /*try {
            Map<String, String> map = textScan.greenTextScan(dto.getContent());
            if(!map.get("suggestion").equals("pass")){
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"评论中有违规内容");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"调用阿里云文本反垃圾功能失败");
        }*/

        //查询发表评论的用户信息
        UserInfoDto userInfoDto = userFeign.findById(userId);

        //3、组装评论数据，保存到MongoDB中
        ApComment apComment = new ApComment();
        apComment.setAuthorId(userId);
        apComment.setAuthorName(userInfoDto.getName());
        apComment.setContent(dto.getContent());
        apComment.setEntryId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setImage(userInfoDto.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType(0);
        apComment.setFlag(0);
        mongoTemplate.insert(apComment);

        //生产评论消息
        ArticleBehaviorMsg articleBehaviorMsg = new ArticleBehaviorMsg(
                dto.getArticleId(),
                1,
                ArticleBehaviorMsg.ArticleBehaviorType.COMMENT);
        kafkaTemplate.send(HotArticleConstants.HOT_ARTICLE_SCORE_STREAM_TOPIC, JsonUtils.toString(articleBehaviorMsg));
    }

    @Override
    public List<CommentVo> loadComment(CommentDto dto) {
        //1、参数校验
        if(dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2、条件查询评论列表
        //根据文章id查询
        Query query = new Query();
        query.addCriteria(Criteria.where("entryId").is(dto.getArticleId()));
        if(dto.getMinLikes() != null && dto.getMinLikes()>0){
            //小于最小点赞数
            query.addCriteria(Criteria.where("likes").lt(dto.getMinLikes()));
        }
        //根据点赞排序（降序）
        query.with(Sort.by(Sort.Direction.DESC,"likes"));
        //设置分页条件
        Pageable pageable = PageRequest.of(dto.getPage().intValue()-1,dto.getSize().intValue());
        query.with(pageable);
        //执行查询
        List<ApComment> commentList = mongoTemplate.find(query, ApComment.class);
        if(CollectionUtils.isEmpty(commentList)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //数据转换
        List<CommentVo> commentVoList = BeanHelper.copyWithCollection(commentList, CommentVo.class);

        //3、获取用id，判断用户登录状态
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            //未登录，直接返回评论列表
            return commentVoList;
        }
        //4、如果用户登录了，需要查询登录用户是否对评论进行了点赞
        //4.1 获取所有评论id
        List<String> commentIds = commentVoList.stream().map(CommentVo::getId).collect(Collectors.toList());
        //4.2 查询登录用户对评论进行了点赞列表
        Query query1 = new Query();
        query1.addCriteria(Criteria.where("authorId").is(userId).and("commentId").in(commentIds).and("operation").is(0));
        List<ApCommentLike> commentLikeList = mongoTemplate.find(query1, ApCommentLike.class);
        //4.3 获取点赞列表中的评论id
        if(!CollectionUtils.isEmpty(commentLikeList)){
            List<String> likeCommentIds = commentLikeList.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());
            //为点赞过的评论operation赋值0
            commentVoList.stream().forEach(commentVo -> {
                //判断点赞的评论中，是否有遍历的commentVo的id值
                if(likeCommentIds.contains(commentVo.getId())){
                    commentVo.setOperation(0);
                }
            });

        }

        return commentVoList;
    }

    @Override
    public void likeComment(CommentLikeDto dto) {
        //1、参数校验
        if(dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2、获取用户id，如果用户登录，先去登录
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }

        //查询评论数据是否存在
        String commentId = dto.getCommentId();
        ApComment apComment = mongoTemplate.findById(commentId, ApComment.class);
        if(apComment==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"点赞的评论数据不存在");
        }
        //3、查询用户是否对当前评论点赞过（一个用户针对同一评论数据只能点赞一次）
        Query query = new Query();
        query.addCriteria(Criteria.where("authorId").is(userId).and("commentId").is(dto.getCommentId()));
        ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
        if(apCommentLike==null && dto.getOperation()==0){
            //4、如果没有查询点赞记录，并且用户是点赞行为，需要更新点赞次数（次数加一），并且记录点赞行为记录
            //记录点赞行为记录
            apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(userId);
            apCommentLike.setOperation(dto.getOperation());
            apCommentLike.setCommentId(dto.getCommentId());
            mongoTemplate.save(apCommentLike);
            //更新点赞次数（次数加一）
            Query query1 = new Query();
            query1.addCriteria(Criteria.where("_id").is(dto.getCommentId()));
            Update update = new Update();
            update.inc("likes");
            mongoTemplate.updateFirst(query1,update,ApComment.class);
        }else if(apCommentLike!=null && dto.getOperation()!=apCommentLike.getOperation()){
            //5、如果查询点赞记录，更新点赞状态，以及点赞次数
            //更新点赞状态
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);

            //点赞次数
            int opt = dto.getOperation()==0?1:-1;
            //如果点赞数量已经是0，即便是取消点赞也不能再减一
            if(opt==-1 && apComment.getLikes()<1){
                return;
            }
            //更新点赞
            Query query1 = new Query();
            query1.addCriteria(Criteria.where("_id").is(dto.getCommentId()));
            Update update = new Update();
            update.inc("likes",opt);
            mongoTemplate.updateFirst(query1,update,ApComment.class);
        }


    }
}
